package com.linglan.common.aop.aspects;

import cn.hutool.core.util.BooleanUtil;
import com.linglan.common.api.R;
import com.linglan.common.utils.LingLanValidator;
import com.linglan.common.utils.ValidationResult;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Map;

@Aspect
@Component
public class ParamValidateAspect {

    /**
     * 这里我们使用注解的形式
     * 当然，我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
     * 切点表达式:   execution(...)
     *
     * execution(public * *(..)) 任意的公共方法
     * execution（* set*（..）） 以set开头的所有的方法
     * execution（* com.LoggerApply.*（..））com.LoggerApply这个类里的所有的方法
     * execution（* com.annotation.*.*（..））com.annotation包下的所有的类的所有的方法
     * execution（* com.annotation..*.*（..））com.annotation包及子包下所有的类的所有的方法
     * execution(* com.annotation..*.*(String,?,Long)) com.annotation包及子包下所有的类的有三个参数，第一个参数为String类型，第二个参数为任意类型，第三个参数为Long类型的方法
     * execution(@annotation(com.lingyejun.annotation.Lingyejun))
     */
    @Pointcut("@annotation(com.linglan.common.aop.annotations.ParamValidate)")
    public void paramValidatePointCut() {}

    @Around("paramValidatePointCut()")
    public Object validateParam(ProceedingJoinPoint joinPoint) throws Throwable {
        ValidationResult validationResult = LingLanValidator.validateEntity(joinPoint.getArgs()[0]);
        if (BooleanUtil.isTrue(validationResult.getHasErrors())) {
            Map<String, String> errorMsg = validationResult.getErrorMsg();
            String value = errorMsg.entrySet().stream().findFirst().get().getValue();
            return R.failed(value);
        }
        return joinPoint.proceed();
    }

}
